package org.streets.extention.quartz.internal;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.streets.extention.quartz.QuartzJob;
import org.streets.extention.quartz.QuartzScheduler;
import org.streets.extention.quartz.QuartzSchedulerException;
import org.streets.extention.quartz.QuartzSchedulerManager;

/**
 * manages the Quartz schedulers.
 * <p/>
 * adding all configured job scheduling bundles to the default or named scheduler.
 *
 * @version $Id: QuartzSchedulerManagerImpl.java 358 2008-11-25 12:52:26Z homburgs $
 */
public class QuartzSchedulerManagerImpl implements QuartzSchedulerManager
{
    private final SchedulerFactory schedulerFactory;
    private final Logger logger;
    private final Map<String, QuartzScheduler> schedulers = Collections.synchronizedMap(new HashMap<String, QuartzScheduler>());

    public QuartzSchedulerManagerImpl(Logger logger, Collection<QuartzJob> quartzJobs) {
    	
        this.logger = logger;
        this.schedulerFactory = new StdSchedulerFactory();;

            for (QuartzJob job : quartzJobs) {
            	String group = job.getGroup();
            	QuartzScheduler qs = getScheduler(group);
            	qs.scheduleJob(job);
            }              
    }

    /**
     * get a scheduler by his id.
     * <p/>
     * if <em>schedulerId</em> is null or length == 0, than returns the default scheduler.
     *
     * @param schedulerId id of the scheduler
     *
     * @return a named scheduler
     */
    public QuartzScheduler getScheduler(String schedulerId) {
    	
    	QuartzScheduler qs = schedulers.get(schedulerId);
    	if (qs == null) {
        	Scheduler scheduler = null;
			try {
				scheduler = schedulerFactory.getScheduler(schedulerId);
            	if (scheduler == null) {
            		scheduler = schedulerFactory.getScheduler();
            	}
			} catch (SchedulerException e) {
				throw new QuartzSchedulerException("Can not get internal Scheduler from scheduler factory!", e);
			}
        	qs = new QuartzScheduler(scheduler, schedulerId);
			schedulers.put(schedulerId, qs);
    	}
    	return qs;
    }

	public void start() {
        List<Scheduler> schedulers;
		try {
			schedulers = CollectionFactory.newList(schedulerFactory.getAllSchedulers());
	        for (Scheduler scheduler : schedulers) {
	        	if (!scheduler.isStarted()) {
	        		scheduler.start();
	        	}
	            logger.info("scheduler ["+scheduler.getSchedulerInstanceId()+"] started");                
	        }
		} catch (SchedulerException e) {			
			throw new QuartzSchedulerException("Start quartz scheduler error!", e);
		}
	}


	public void shutdown() {
        try {
            List<Scheduler> schedulers = CollectionFactory.newList(schedulerFactory.getAllSchedulers());
            for (Scheduler scheduler : schedulers) {
            	if (!scheduler.isShutdown()) {
            		scheduler.shutdown();
            	}
            }
        } catch (Exception e) {
            throw new QuartzSchedulerException("Shut down schedulers error", e);
        }
	}	
}
